/*    Copyright 2010 Tobias Marschall
 *
 *    This file is part of MoSDi.
 *
 *    MoSDi is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    MoSDi is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with MoSDi.  If not, see <http://www.gnu.org/licenses/>.
 */

package mosdi.tests;

import junit.framework.TestCase;
import mosdi.util.Combinatorics;

public class CombinatoricsTest extends TestCase {
	
	public void testFactorial() {
		assertEquals(1L, Combinatorics.factorial(0));
		assertEquals(1L, Combinatorics.factorial(1));
		assertEquals(2L, Combinatorics.factorial(2));
		assertEquals(6L, Combinatorics.factorial(3));
		assertEquals(24L, Combinatorics.factorial(4));
		assertEquals(120L, Combinatorics.factorial(5));
		assertEquals(720L, Combinatorics.factorial(6));
		assertEquals(5040L, Combinatorics.factorial(7));
		assertEquals(40320L, Combinatorics.factorial(8));
		assertEquals(362880L, Combinatorics.factorial(9));
		assertEquals(3628800L, Combinatorics.factorial(10));
		assertEquals(39916800L, Combinatorics.factorial(11));
		assertEquals(479001600L, Combinatorics.factorial(12));
		assertEquals(6227020800L, Combinatorics.factorial(13));
		assertEquals(87178291200L, Combinatorics.factorial(14));
		assertEquals(1307674368000L, Combinatorics.factorial(15));
		assertEquals(20922789888000L, Combinatorics.factorial(16));
		assertEquals(355687428096000L, Combinatorics.factorial(17));
		assertEquals(6402373705728000L, Combinatorics.factorial(18));
		assertEquals(121645100408832000L, Combinatorics.factorial(19));
		assertEquals(2432902008176640000L, Combinatorics.factorial(20));
		try {
			Combinatorics.factorial(21);
			fail("Expected IllegalArgumentException.");
		} catch (IllegalArgumentException e) { }
		assertEquals("30414093201713378043612608166064768844377641568960512000000000000",Combinatorics.bigIntFactorial(50).toString());
		assertEquals(148.47776695177302, Combinatorics.logFactorial(50), 1e-10);
	}

	public void testBinomial() {
		assertEquals(210, Combinatorics.binomial(10,4));
		assertEquals(227068876035237600L, Combinatorics.binomial(65,23));
		assertEquals(207374699821536L, Combinatorics.binomial(65,15));
		assertEquals(3247943160L, Combinatorics.binomial(35,15));
		assertEquals(183579396, Combinatorics.binomial(35,25));
		assertEquals(3169870830126L, Combinatorics.binomial(45,25));
		assertEquals(17310309456440L, Combinatorics.binomial(100,90));
		assertEquals(5163222847461899400L, Combinatorics.binomial(75,22));
		try {
			Combinatorics.binomial(75,23);
			fail("Expected IllegalArgumentException.");
		} catch (IllegalArgumentException e) { }
		assertEquals("4621498022322629883980226171186143574727600", Combinatorics.bigIntBinomial(150, 60).toString());
		assertEquals(98.23929280554276, Combinatorics.logBinomial(150, 60), 1e-10);
	}

	public void testMultinomial() {
		int[] k1 = {6,0,8,1,5};
		int[] k2 = {4,4,4,3,5};
		int[] k3 = {10,10,10};
		int[] k4 = {5,5,5,5,5,5};
		int[] k5 = {5,5,5,5,5,5,5,5,5,5};
		assertEquals(698377680L, Combinatorics.multinomial(20, k1));
		assertEquals(244432188000L, Combinatorics.multinomial(20, k2));
		assertEquals(5550996791340L, Combinatorics.multinomial(30, k3));
		try {
			Combinatorics.multinomial(30, k4);
			fail("Expected IllegalArgumentException.");
		} catch (IllegalArgumentException e) { }
		assertEquals("49120458506088132224064306071170476903628800", Combinatorics.bigIntMultinomial(50, k5).toString());
		assertEquals(100.60284952395257, Combinatorics.logMultinomial(50, k5), 1e-10);
	}
}
